/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation for mapping web requests onto methods in request-handling classes with
 * flexible method signatures.
 *
 * <p>
 * Both Spring MVC and Spring WebFlux support this annotation through a
 * {@code RequestMappingHandlerMapping} and {@code RequestMappingHandlerAdapter} in their
 * respective modules and package structure. For the exact list of supported handler
 * method arguments and return types in each, please use the reference documentation links
 * below:
 * <ul>
 * <li>Spring MVC <a href=
 * "https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-arguments">Method
 * Arguments</a> and <a href=
 * "https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-return-types">Return
 * Values</a></li>
 * <li>Spring WebFlux <a href=
 * "https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-ann-arguments">Method
 * Arguments</a> and <a href=
 * "https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-ann-return-types">Return
 * Values</a></li>
 * </ul>
 *
 * <p>
 * <strong>Note:</strong> This annotation can be used both at the class and at the method
 * level. In most cases, at the method level applications will prefer to use one of the
 * HTTP method specific variants {@link GetMapping @GetMapping},
 * {@link PostMapping @PostMapping}, {@link PutMapping @PutMapping},
 * {@link DeleteMapping @DeleteMapping}, or {@link PatchMapping @PatchMapping}.
 * </p>
 *
 * <p>
 * <b>NOTE:</b> When using controller interfaces (e.g. for AOP proxying), make sure to
 * consistently put <i>all</i> your mapping annotations - such as {@code @RequestMapping}
 * and {@code @SessionAttributes} - on the controller <i>interface</i> rather than on the
 * implementation class.
 *
 * @author Juergen Hoeller
 * @author Arjen Poutsma
 * @author Sam Brannen
 * @since 2.5
 * @see GetMapping
 * @see PostMapping
 * @see PutMapping
 * @see DeleteMapping
 * @see PatchMapping
 * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
 * @see org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {

	/**
	 * Assign a name to this mapping.
	 * <p>
	 * <b>Supported at the type level as well as at the method level!</b> When used on
	 * both levels, a combined name is derived by concatenation with "#" as separator.
	 * @see org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder
	 * @see org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy
	 */
	String name() default "";

	/**
	 * The primary mapping expressed by this annotation.
	 * <p>
	 * This is an alias for {@link #path}. For example {@code @RequestMapping("/foo")} is
	 * equivalent to {@code @RequestMapping(path="/foo")}.
	 * <p>
	 * <b>Supported at the type level as well as at the method level!</b> When used at the
	 * type level, all method-level mappings inherit this primary mapping, narrowing it
	 * for a specific handler method.
	 */
	String[] value() default {};

	/**
	 * The path mapping URIs (e.g. "/myPath.do"). Ant-style path patterns are also
	 * supported (e.g. "/myPath/*.do"). At the method level, relative paths (e.g.
	 * "edit.do") are supported within the primary mapping expressed at the type level.
	 * Path mapping URIs may contain placeholders (e.g. "/${connect}").
	 * <p>
	 * <b>Supported at the type level as well as at the method level!</b> When used at the
	 * type level, all method-level mappings inherit this primary mapping, narrowing it
	 * for a specific handler method.
	 * @see org.springframework.web.bind.annotation.ValueConstants#DEFAULT_NONE
	 * @since 4.2
	 */
	String[] path() default {};

	/**
	 * The HTTP request methods to map to, narrowing the primary mapping: GET, POST, HEAD,
	 * OPTIONS, PUT, PATCH, DELETE, TRACE.
	 * <p>
	 * <b>Supported at the type level as well as at the method level!</b> When used at the
	 * type level, all method-level mappings inherit this HTTP method restriction (i.e.
	 * the type-level restriction gets checked before the handler method is even
	 * resolved).
	 */
	RequestMethod[] method() default {};

	/**
	 * The parameters of the mapped request, narrowing the primary mapping.
	 * <p>
	 * Same format for any environment: a sequence of "myParam=myValue" style expressions,
	 * with a request only mapped if each such parameter is found to have the given value.
	 * Expressions can be negated by using the "!=" operator, as in "myParam!=myValue".
	 * "myParam" style expressions are also supported, with such parameters having to be
	 * present in the request (allowed to have any value). Finally, "!myParam" style
	 * expressions indicate that the specified parameter is <i>not</i> supposed to be
	 * present in the request.
	 * <p>
	 * <b>Supported at the type level as well as at the method level!</b> When used at the
	 * type level, all method-level mappings inherit this parameter restriction (i.e. the
	 * type-level restriction gets checked before the handler method is even resolved).
	 * <p>
	 * Parameter mappings are considered as restrictions that are enforced at the type
	 * level. The primary path mapping (i.e. the specified URI value) still has to
	 * uniquely identify the target handler, with parameter mappings simply expressing
	 * preconditions for invoking the handler.
	 */
	String[] params() default {};

	/**
	 * The headers of the mapped request, narrowing the primary mapping.
	 * <p>
	 * Same format for any environment: a sequence of "My-Header=myValue" style
	 * expressions, with a request only mapped if each such header is found to have the
	 * given value. Expressions can be negated by using the "!=" operator, as in
	 * "My-Header!=myValue". "My-Header" style expressions are also supported, with such
	 * headers having to be present in the request (allowed to have any value). Finally,
	 * "!My-Header" style expressions indicate that the specified header is <i>not</i>
	 * supposed to be present in the request.
	 * <p>
	 * Also supports media type wildcards (*), for headers such as Accept and
	 * Content-Type. For instance, <pre class="code">
	 * &#064;RequestMapping(value = "/something", headers = "content-type=text/*")
	 * </pre> will match requests with a Content-Type of "text/html", "text/plain", etc.
	 * <p>
	 * <b>Supported at the type level as well as at the method level!</b> When used at the
	 * type level, all method-level mappings inherit this header restriction (i.e. the
	 * type-level restriction gets checked before the handler method is even resolved).
	 * @see org.springframework.http.MediaType
	 */
	String[] headers() default {};

	/**
	 * The consumable media types of the mapped request, narrowing the primary mapping.
	 * <p>
	 * The format is a single media type or a sequence of media types, with a request only
	 * mapped if the {@code Content-Type} matches one of these media types. Examples:
	 * <pre class="code">
	 * consumes = "text/plain"
	 * consumes = {"text/plain", "application/*"}
	 * </pre> Expressions can be negated by using the "!" operator, as in "!text/plain",
	 * which matches all requests with a {@code Content-Type} other than "text/plain".
	 * <p>
	 * <b>Supported at the type level as well as at the method level!</b> When used at the
	 * type level, all method-level mappings override this consumes restriction.
	 * @see org.springframework.http.MediaType
	 * @see javax.servlet.http.HttpServletRequest#getContentType()
	 */
	String[] consumes() default {};

	/**
	 * The producible media types of the mapped request, narrowing the primary mapping.
	 * <p>
	 * The format is a single media type or a sequence of media types, with a request only
	 * mapped if the {@code Accept} matches one of these media types. Examples:
	 * <pre class="code">
	 * produces = "text/plain"
	 * produces = {"text/plain", "application/*"}
	 * produces = MediaType.APPLICATION_JSON_UTF8_VALUE
	 * </pre>
	 * <p>
	 * It affects the actual content type written, for example to produce a JSON response
	 * with UTF-8 encoding,
	 * {@link org.springframework.http.MediaType#APPLICATION_JSON_UTF8_VALUE} should be
	 * used.
	 * <p>
	 * Expressions can be negated by using the "!" operator, as in "!text/plain", which
	 * matches all requests with a {@code Accept} other than "text/plain".
	 * <p>
	 * <b>Supported at the type level as well as at the method level!</b> When used at the
	 * type level, all method-level mappings override this produces restriction.
	 * @see org.springframework.http.MediaType
	 */
	String[] produces() default {};

}
